<script setup lang="ts">
import { ref } from 'vue';
import io from 'socket.io-client';

const localVideo = ref<HTMLVideoElement | null>(null);
const remoteVideo = ref<HTMLVideoElement | null>(null);
const localStream = ref<MediaStream | null>(null);
let pc: RTCPeerConnection;
const socket = io('http://10.130.15.112:3000');

const start = async () => {
  try {
    localStream.value = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
    if (localVideo.value) {
      localVideo.value.srcObject = localStream.value;
    }
  } catch (e) {
    console.error('Error accessing media devices.', e);
  }
};

const call = async () => {
  const configuration = {};
  pc = new RTCPeerConnection(configuration);

  pc.onicecandidate = e => {
    socket.emit('ice-candidate', e.candidate);
  };

  pc.ontrack = e => {
    if (remoteVideo.value && e.streams[0]) {
      remoteVideo.value.srcObject = e.streams[0];
    }
  };

  if (localStream.value) {
    localStream.value.getTracks().forEach(track => pc?.addTrack(track, localStream.value!));
  }

  try {
    const offer = await pc.createOffer();
    await pc.setLocalDescription(offer);
    socket.emit('offer', offer);
  } catch (e) {
    console.error('Error creating offer/answer.', e);
  }
};

const hangup = () => {
  pc?.close();
};

socket.on('offer', async offer => {
  if (!pc) {
    const configuration = {};
    pc = new RTCPeerConnection(configuration);

    pc.onicecandidate = e => {
      if (e.candidate) {
        socket.emit('ice-candidate', e.candidate);
      }
    };

    pc.ontrack = e => {
      if (remoteVideo.value && e.streams[0]) {
        remoteVideo.value.srcObject = e.streams[0] ?? null;
      }
    };

    if (localStream.value) {
      localStream.value.getTracks().forEach(track => pc?.addTrack(track, localStream.value!));
    }
  }

  try {
    await pc.setRemoteDescription(offer);
    const answer = await pc.createAnswer();
    await pc.setLocalDescription(answer);
    socket.emit('answer', answer);
  } catch (e) {
    console.error('Error handling offer.', e);
  }
});

socket.on('answer', async answer => {
  if (pc) {
    try {
      await pc.setRemoteDescription(answer);
    } catch (e) {
      console.error('Error handling answer.', e);
    }
  }
});

socket.on('ice-candidate', async candidate => {
  if (pc) {
    try {
      await pc.addIceCandidate(candidate);
    } catch (e) {
      console.error('Error adding received ICE candidate', e);
    }
  }
});
</script>

<template>
  <div>
    <h1>WebRTC Video Call</h1>
    <video ref="localVideo" autoplay playsinline></video>
    <video ref="remoteVideo" autoplay playsinline></video>
    <br />
    <button @click="start">Start</button>
    <button @click="call">Call</button>
    <button @click="hangup">Hang Up</button>
  </div>
</template>

<style scoped>
video {
  width: 300px;
  height: 200px;
  background-color: black;
  margin: 10px;
}
</style>
